From 6d6ca3b27e1ad2ecd7cbc0b3a611251c24e47e66 Mon Sep 17 00:00:00 2001 From: "cl349@firebug.cl.cam.ac.uk[cl349]" Date: Wed, 11 May 2005 15:05:07 +0000 Subject: [PATCH] bitkeeper revision 1.1389.15.13 (42821f23dLMLc5Ql8Y-rUwoatYBI6g) Split out context fetching into separate DOM0 op make GETDOMAININFO a little more sensible with respect to MP make coredump dump all cpu contexts Signed-off-by: Kip Macy Signed-off-by: Christian Limpach --- tools/libxc/xc.h | 14 ++--- tools/libxc/xc_core.c | 24 ++++++--- tools/libxc/xc_domain.c | 38 ++++++-------- tools/libxc/xc_linux_build.c | 9 +++- tools/libxc/xc_linux_restore.c | 2 - tools/libxc/xc_linux_save.c | 26 +++++++--- tools/libxc/xc_plan9_build.c | 10 ++-- tools/libxc/xc_private.c | 15 +++--- tools/libxc/xc_ptrace.c | 11 ++-- tools/libxc/xc_vmx_build.c | 9 +++- xen/common/dom0_ops.c | 94 +++++++++++++++++++++++++++------- xen/include/public/dom0_ops.h | 14 ++++- 12 files changed, 177 insertions(+), 89 deletions(-) diff --git a/tools/libxc/xc.h b/tools/libxc/xc.h index 68a1fb6abc..b02426d5ea 100644 --- a/tools/libxc/xc.h +++ b/tools/libxc/xc.h @@ -110,8 +110,10 @@ int xc_waitdomain_core(int domain, typedef struct { u32 domid; - unsigned int cpu; + unsigned int flags; + unsigned int processors; unsigned int vcpus; + u16 n_vcpus; unsigned int dying:1, crashed:1, shutdown:1, paused:1, blocked:1, running:1; unsigned int shutdown_reason; /* only meaningful if shutdown==1 */ @@ -199,11 +201,11 @@ int xc_domain_getinfo(int xc_handle, * domain * @return 0 on success, -1 on failure */ -int xc_domain_getfullinfo(int xc_handle, - u32 domid, - u32 vcpu, - xc_domaininfo_t *info, - vcpu_guest_context_t *ctxt); +int xc_domain_get_vcpu_context(int xc_handle, + u32 domid, + u32 vcpu, + vcpu_guest_context_t *ctxt); + int xc_domain_setcpuweight(int xc_handle, u32 domid, float weight); diff --git a/tools/libxc/xc_core.c b/tools/libxc/xc_core.c index 84ef16bf37..50fe1c26aa 100644 --- a/tools/libxc/xc_core.c +++ b/tools/libxc/xc_core.c @@ -7,6 +7,7 @@ /* number of pages to write at a time */ #define DUMP_INCREMENT 4 * 1024 #define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK) + static int copy_from_domain_page(int xc_handle, u32 domid, @@ -28,13 +29,14 @@ xc_domain_dumpcore(int xc_handle, u32 domid, const char *corename) { - vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt; unsigned long nr_pages; unsigned long *page_array; - xc_domaininfo_t st_info, *info = &st_info; + xc_dominfo_t info; int i, dump_fd; char *dump_mem, *dump_mem_start = NULL; struct xc_core_header header; + vcpu_guest_context_t ctxt[MAX_VIRT_CPUS]; + if ((dump_fd = open(corename, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)) < 0) { PERROR("Could not open corefile %s: %s", corename, strerror(errno)); @@ -46,14 +48,22 @@ xc_domain_dumpcore(int xc_handle, goto error_out; } - if (xc_domain_getfullinfo(xc_handle, domid, 0/* XXX hardcode */, info, ctxt)) { - PERROR("Could not get full info for domain"); + if (xc_domain_getinfo(xc_handle, domid, 1, &info)) { + PERROR("Could not get info for domain"); goto error_out; } + + for (i = 0; i < info.n_vcpus; i++) { + if (xc_domain_get_vcpu_context(xc_handle, domid, i, &ctxt[i])) { + PERROR("Could not get all vcpu contexts for domain"); + goto error_out; + } + } + + nr_pages = info.nr_pages; - nr_pages = info->tot_pages; header.xch_magic = 0xF00FEBED; - header.xch_nr_vcpus = 1; /* no interface to query at the moment */ + header.xch_nr_vcpus = info.n_vcpus; header.xch_nr_pages = nr_pages; header.xch_ctxt_offset = sizeof(struct xc_core_header); header.xch_index_offset = sizeof(struct xc_core_header) + @@ -62,7 +72,7 @@ xc_domain_dumpcore(int xc_handle, sizeof(vcpu_guest_context_t) + nr_pages * sizeof(unsigned long)); write(dump_fd, &header, sizeof(struct xc_core_header)); - write(dump_fd, ctxt, sizeof(st_ctxt)); + write(dump_fd, &ctxt, sizeof(ctxt[0]) * info.n_vcpus); if ((page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) { printf("Could not allocate memory\n"); diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index 12a724b2f2..ac82bcffd2 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -112,14 +112,12 @@ int xc_domain_getinfo(int xc_handle, { op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = (domid_t)next_domid; - op.u.getdomaininfo.exec_domain = 0; // FIX ME?!? - op.u.getdomaininfo.ctxt = NULL; /* no exec context info, thanks. */ if ( (rc = do_dom0_op(xc_handle, &op)) < 0 ) break; - info->domid = (u16)op.u.getdomaininfo.domain; - - info->cpu = - (op.u.getdomaininfo.flags>>DOMFLAGS_CPUSHIFT) & DOMFLAGS_CPUMASK; + info->domid = (u16)op.u.getdomaininfo.domain; + info->processors = op.u.getdomaininfo.processors; + info->n_vcpus = op.u.getdomaininfo.n_active_vcpus; + info->flags = op.u.getdomaininfo.flags; info->dying = !!(op.u.getdomaininfo.flags & DOMFLAGS_DYING); info->crashed = !!(op.u.getdomaininfo.flags & DOMFLAGS_CRASHED); @@ -142,28 +140,27 @@ int xc_domain_getinfo(int xc_handle, memcpy(&info->cpumap, &op.u.getdomaininfo.cpumap, sizeof(info->cpumap)); - next_domid = (u16)op.u.getdomaininfo.domain + 1; - info++; + next_domid = (u16)op.u.getdomaininfo.domain + 1; + info++; } - if(!nr_doms) return rc; + if( !nr_doms ) return rc; return nr_doms; } -int xc_domain_getfullinfo(int xc_handle, - u32 domid, - u32 vcpu, - xc_domaininfo_t *info, - vcpu_guest_context_t *ctxt) +int xc_domain_get_vcpu_context(int xc_handle, + u32 domid, + u32 vcpu, + vcpu_guest_context_t *ctxt) { int rc, errno_saved; dom0_op_t op; - op.cmd = DOM0_GETDOMAININFO; - op.u.getdomaininfo.domain = (domid_t)domid; - op.u.getdomaininfo.exec_domain = (u16)vcpu; - op.u.getdomaininfo.ctxt = ctxt; + op.cmd = DOM0_GETVCPUCONTEXT; + op.u.getvcpucontext.domain = (domid_t)domid; + op.u.getvcpucontext.exec_domain = (u16)vcpu; + op.u.getvcpucontext.ctxt = ctxt; if ( (ctxt != NULL) && ((rc = mlock(ctxt, sizeof(*ctxt))) != 0) ) @@ -178,10 +175,7 @@ int xc_domain_getfullinfo(int xc_handle, errno = errno_saved; } - if ( info != NULL ) - memcpy(info, &op.u.getdomaininfo, sizeof(*info)); - - if ( ((u16)op.u.getdomaininfo.domain != domid) && (rc > 0) ) + if ( rc > 0 ) return -ESRCH; else return rc; diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index abf427f87f..d5d344cfee 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -356,14 +356,19 @@ int xc_linux_build(int xc_handle, op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = (domid_t)domid; - op.u.getdomaininfo.exec_domain = 0; - op.u.getdomaininfo.ctxt = ctxt; if ( (do_dom0_op(xc_handle, &op) < 0) || ((u16)op.u.getdomaininfo.domain != domid) ) { PERROR("Could not get info on domain"); goto error_out; } + + if ( xc_domain_get_vcpu_context(xc_handle, domid, 0, ctxt) ) + { + PERROR("Could not get vcpu context"); + goto error_out; + } + if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) || (ctxt->pt_base != 0) ) { diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index 3d3f4c1e18..6442e3926a 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -181,8 +181,6 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) /* Get the domain's shared-info frame. */ op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = (domid_t)dom; - op.u.getdomaininfo.exec_domain = 0; - op.u.getdomaininfo.ctxt = NULL; if ( do_dom0_op(xc_handle, &op) < 0 ) { xcio_error(ioctxt, "Could not get information on new domain"); diff --git a/tools/libxc/xc_linux_save.c b/tools/libxc/xc_linux_save.c index f8a28cf43f..43d12838ba 100644 --- a/tools/libxc/xc_linux_save.c +++ b/tools/libxc/xc_linux_save.c @@ -324,7 +324,7 @@ static int analysis_phase( int xc_handle, u32 domid, int suspend_and_state(int xc_handle, XcIOContext *ioctxt, - xc_domaininfo_t *info, + xc_dominfo_t *info, vcpu_guest_context_t *ctxt) { int i=0; @@ -333,13 +333,18 @@ int suspend_and_state(int xc_handle, XcIOContext *ioctxt, retry: - if ( xc_domain_getfullinfo(xc_handle, ioctxt->domain, /* FIXME */ 0, - info, ctxt) ) + if ( xc_domain_getinfo(xc_handle, ioctxt->domain, 1, info) ) { xcio_error(ioctxt, "Could not get full domain info"); return -1; } + if ( xc_domain_get_vcpu_context(xc_handle, ioctxt->domain, 0 /* XXX */, + ctxt) ) + { + xcio_error(ioctxt, "Could not get vcpu context"); + } + if ( (info->flags & (DOMFLAGS_SHUTDOWN | (SHUTDOWN_suspend< 1024*1024 ){ diff --git a/tools/libxc/xc_plan9_build.c b/tools/libxc/xc_plan9_build.c index 3260661acc..2d437080f1 100644 --- a/tools/libxc/xc_plan9_build.c +++ b/tools/libxc/xc_plan9_build.c @@ -440,17 +440,21 @@ xc_plan9_build(int xc_handle, op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = (domid_t) domid; - op.u.getdomaininfo.exec_domain = 0; - op.u.getdomaininfo.ctxt = ctxt; if ((do_dom0_op(xc_handle, &op) < 0) || ((u32) op.u.getdomaininfo.domain != domid)) { PERROR("Could not get info on domain"); goto error_out; } DPRINTF(("xc_get_tot_pages returns %ld pages\n", tot_pages)); + + if ( xc_domain_get_vcpu_context(xc_handle, domid, 0, ctxt) ) + { + PERROR("Could not get vcpu context"); + goto error_out; + } if (!(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) - || (op.u.getdomaininfo.ctxt->pt_base != 0)) { + || (ctxt->pt_base != 0)) { ERROR("Domain is already constructed"); goto error_out; } diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 15327ccdbb..39318bc4fa 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -173,17 +173,16 @@ long long xc_domain_get_cpu_usage( int xc_handle, domid_t domid, int vcpu ) { dom0_op_t op; - op.cmd = DOM0_GETDOMAININFO; - op.u.getdomaininfo.domain = (domid_t)domid; - op.u.getdomaininfo.exec_domain = (u16)vcpu; - op.u.getdomaininfo.ctxt = NULL; - if ( (do_dom0_op(xc_handle, &op) < 0) || - ((u16)op.u.getdomaininfo.domain != domid) ) + op.cmd = DOM0_GETVCPUCONTEXT; + op.u.getvcpucontext.domain = (domid_t)domid; + op.u.getvcpucontext.exec_domain = (u16)vcpu; + op.u.getvcpucontext.ctxt = NULL; + if ( (do_dom0_op(xc_handle, &op) < 0) ) { PERROR("Could not get info on domain"); return -1; } - return op.u.getdomaininfo.cpu_time; + return op.u.getvcpucontext.cpu_time; } @@ -258,8 +257,6 @@ long xc_get_tot_pages(int xc_handle, u32 domid) dom0_op_t op; op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = (domid_t)domid; - op.u.getdomaininfo.exec_domain = 0; - op.u.getdomaininfo.ctxt = NULL; return (do_dom0_op(xc_handle, &op) < 0) ? -1 : op.u.getdomaininfo.tot_pages; } diff --git a/tools/libxc/xc_ptrace.c b/tools/libxc/xc_ptrace.c index 63efdd7cb9..ca051fab97 100644 --- a/tools/libxc/xc_ptrace.c +++ b/tools/libxc/xc_ptrace.c @@ -71,7 +71,7 @@ struct gdb_regs { #define FETCH_REGS(cpu) \ if (!regs_valid[cpu]) \ { \ - int retval = xc_domain_getfullinfo(xc_handle, domid, cpu, NULL, &ctxt[cpu]); \ + int retval = xc_domain_get_vcpu_context(xc_handle, domid, cpu, &ctxt[cpu]); \ if (retval) \ goto error_out; \ cr3[cpu] = ctxt[cpu].pt_base; /* physical address */ \ @@ -221,7 +221,6 @@ xc_waitdomain(int domain, int *status, int options) { dom0_op_t op; int retval; - vcpu_guest_context_t ctxt; struct timespec ts; ts.tv_sec = 0; ts.tv_nsec = 10*1000*1000; @@ -234,12 +233,10 @@ xc_waitdomain(int domain, int *status, int options) } op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = domain; - op.u.getdomaininfo.exec_domain = 0; - op.u.getdomaininfo.ctxt = &ctxt; retry: retval = do_dom0_op(xc_handle, &op); - if (retval) { + if (retval || op.u.getdomaininfo.domain != domain) { printf("getdomaininfo failed\n"); goto done; } @@ -325,10 +322,8 @@ xc_ptrace(enum __ptrace_request request, u32 domid, long eaddr, long edata) case PTRACE_ATTACH: op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = domid; - op.u.getdomaininfo.exec_domain = 0; - op.u.getdomaininfo.ctxt = NULL; retval = do_dom0_op(xc_handle, &op); - if (retval) { + if (retval || op.u.getdomaininfo.domain != domid) { perror("dom0 op failed"); goto error_out; } diff --git a/tools/libxc/xc_vmx_build.c b/tools/libxc/xc_vmx_build.c index a89b783fee..eeb8a57df6 100644 --- a/tools/libxc/xc_vmx_build.c +++ b/tools/libxc/xc_vmx_build.c @@ -543,14 +543,19 @@ int xc_vmx_build(int xc_handle, op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = (domid_t)domid; - op.u.getdomaininfo.exec_domain = 0; - op.u.getdomaininfo.ctxt = ctxt; if ( (do_dom0_op(xc_handle, &op) < 0) || ((u16)op.u.getdomaininfo.domain != domid) ) { PERROR("Could not get info on domain"); goto error_out; } + + if ( xc_domain_get_vcpu_context(xc_handle, domid, 0, ctxt) ) + { + PERROR("Could not get vcpu context"); + goto error_out; + } + if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) || (ctxt->pt_base != 0) ) { diff --git a/xen/common/dom0_ops.c b/xen/common/dom0_ops.c index bae4a00caa..e4e3fe74ea 100644 --- a/xen/common/dom0_ops.c +++ b/xen/common/dom0_ops.c @@ -299,9 +299,16 @@ long do_dom0_op(dom0_op_t *u_dom0_op) case DOM0_GETDOMAININFO: { - struct vcpu_guest_context *c; - struct domain *d; - struct exec_domain *ed; + struct domain *d; + struct exec_domain *ed; + u64 cpu_time = 0; + int vcpu_count = 0; + u32 processors = 0; + int flags = DOMFLAGS_PAUSED | DOMFLAGS_BLOCKED; + +#if MAX_VIRT_CPUS > 32 +#error "update processors field in GETDOMAININFO" +#endif read_lock(&domlist_lock); @@ -322,13 +329,6 @@ long do_dom0_op(dom0_op_t *u_dom0_op) op->u.getdomaininfo.domain = d->id; - if ( (op->u.getdomaininfo.exec_domain >= MAX_VIRT_CPUS) || - !d->exec_domain[op->u.getdomaininfo.exec_domain] ) - { - ret = -EINVAL; - break; - } - memset(&op->u.getdomaininfo.vcpu_to_cpu, -1, sizeof(op->u.getdomaininfo.vcpu_to_cpu)); memset(&op->u.getdomaininfo.cpumap, 0, @@ -338,28 +338,86 @@ long do_dom0_op(dom0_op_t *u_dom0_op) op->u.getdomaininfo.cpumap[ed->id] = ed->cpumap; } - ed = d->exec_domain[op->u.getdomaininfo.exec_domain]; + /* + * - domain is marked as paused or blocked only if all its vcpus + * are paused or blocked + * - domain is marked as running if any of its vcpus is running + */ + + for_each_exec_domain(d, ed) + { + if (!((flags & DOMFLAGS_PAUSED) && test_bit(EDF_CTRLPAUSE, &ed->flags))) + flags &= ~DOMFLAGS_PAUSED; + if (!((flags & DOMFLAGS_BLOCKED) && test_bit(EDF_BLOCKED, &ed->flags))) + flags &= ~DOMFLAGS_BLOCKED; + flags |= (test_bit(EDF_RUNNING, &ed->flags) ? DOMFLAGS_RUNNING : 0); + + set_bit(ed->processor, &processors); + if ( ed->cpu_time > cpu_time ) + cpu_time += ed->cpu_time; + vcpu_count++; + } + op->u.getdomaininfo.n_active_vcpus = vcpu_count; + op->u.getdomaininfo.cpu_time = cpu_time; op->u.getdomaininfo.flags = (test_bit( DF_DYING, &d->flags) ? DOMFLAGS_DYING : 0) | (test_bit( DF_CRASHED, &d->flags) ? DOMFLAGS_CRASHED : 0) | (test_bit( DF_SHUTDOWN, &d->flags) ? DOMFLAGS_SHUTDOWN : 0) | - (test_bit(EDF_CTRLPAUSE, &ed->flags) ? DOMFLAGS_PAUSED : 0) | - (test_bit(EDF_BLOCKED, &ed->flags) ? DOMFLAGS_BLOCKED : 0) | - (test_bit(EDF_RUNNING, &ed->flags) ? DOMFLAGS_RUNNING : 0); + flags; - op->u.getdomaininfo.flags |= ed->processor << DOMFLAGS_CPUSHIFT; op->u.getdomaininfo.flags |= d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT; + op->u.getdomaininfo.processors = processors; op->u.getdomaininfo.tot_pages = d->tot_pages; op->u.getdomaininfo.max_pages = d->max_pages; - op->u.getdomaininfo.cpu_time = ed->cpu_time; op->u.getdomaininfo.n_vcpu = d->shared_info->n_vcpu; op->u.getdomaininfo.shared_info_frame = __pa(d->shared_info) >> PAGE_SHIFT; - if ( op->u.getdomaininfo.ctxt != NULL ) + if ( copy_to_user(u_dom0_op, op, sizeof(*op)) ) + ret = -EINVAL; + + put_domain(d); + } + break; + + case DOM0_GETVCPUCONTEXT: + { + struct vcpu_guest_context *c; + struct domain *d; + struct exec_domain *ed; + int active_index = 0; + int exec_domain_index; + + exec_domain_index = op->u.getvcpucontext.exec_domain; + d = find_domain_by_id(op->u.getvcpucontext.domain); + + if ( d == NULL ) + { + ret = -ESRCH; + break; + } + + if ( (exec_domain_index >= MAX_VIRT_CPUS) ) + { + ret = -EINVAL; + break; + } + + for_each_exec_domain(d, ed) + { + if ( exec_domain_index == active_index ) + { + op->u.getvcpucontext.exec_domain = ed->id; + break; + } + active_index++; + } + op->u.getvcpucontext.cpu_time = ed->cpu_time; + + if ( op->u.getvcpucontext.ctxt != NULL ) { if ( (c = xmalloc(struct vcpu_guest_context)) == NULL ) { @@ -376,7 +434,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op) if ( ed != current ) exec_domain_unpause(ed); - if ( copy_to_user(op->u.getdomaininfo.ctxt, c, sizeof(*c)) ) + if ( copy_to_user(op->u.getvcpucontext.ctxt, c, sizeof(*c)) ) ret = -EINVAL; xfree(c); diff --git a/xen/include/public/dom0_ops.h b/xen/include/public/dom0_ops.h index b07b68d773..59f0e6e044 100644 --- a/xen/include/public/dom0_ops.h +++ b/xen/include/public/dom0_ops.h @@ -70,7 +70,7 @@ typedef struct { typedef struct { /* IN variables. */ domid_t domain; /* NB. IN/OUT variable. */ - u16 exec_domain; + u16 n_active_vcpus; /* # of vcpus currently active */ /* OUT variables. */ #define DOMFLAGS_DYING (1<<0) /* Domain is scheduled to die. */ #define DOMFLAGS_CRASHED (1<<1) /* Crashed domain; frozen for postmortem. */ @@ -83,7 +83,7 @@ typedef struct { #define DOMFLAGS_SHUTDOWNMASK 255 /* DOMFLAGS_SHUTDOWN guest-supplied code. */ #define DOMFLAGS_SHUTDOWNSHIFT 16 u32 flags; - vcpu_guest_context_t *ctxt; /* NB. IN/OUT variable. */ + u32 processors; memory_t tot_pages; memory_t max_pages; memory_t shared_info_frame; /* MFN of shared_info struct */ @@ -345,6 +345,15 @@ typedef struct { u16 allow_access; /* allow or deny access to range? */ } dom0_ioport_permission_t; +#define DOM0_GETVCPUCONTEXT 37 +typedef struct { + domid_t domain; /* domain to be affected */ + u16 exec_domain; /* NB. IN: nth active cpu / OUT: actual cpu # */ + vcpu_guest_context_t *ctxt; /* NB. IN/OUT variable. */ + u64 cpu_time; +} dom0_getvcpucontext_t; + + typedef struct { u32 cmd; u32 interface_version; /* DOM0_INTERFACE_VERSION */ @@ -376,6 +385,7 @@ typedef struct { dom0_perfccontrol_t perfccontrol; dom0_microcode_t microcode; dom0_ioport_permission_t ioport_permission; + dom0_getvcpucontext_t getvcpucontext; } u; } dom0_op_t; -- 2.30.2